home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
TECHNICA
/
COMPUTER
/
H254.ZIP
/
IRITSM3S.ZIP
/
IRIT
/
OVERLOAD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-21
|
21KB
|
504 lines
/*****************************************************************************
* "Irit" - the 3d polygonal solid modeller. *
* *
* Written by: Gershon Elber Ver 0.2, Mar. 1990 *
******************************************************************************
* Module to handle overloaded operators for the input parser module. *
* Note this module should be accessed by Input Parser only (InptPrsr.c). *
*****************************************************************************/
#ifdef __MSDOS__
#include <alloc.h>
#endif /* __MSDOS__ */
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include "program.h"
#include "allocate.h"
#include "booleang.h"
#include "freeform.h"
#include "geomat3d.h"
#include "inptprsg.h"
#include "inptprsl.h"
#include "objects.h"
#include "overload.h"
/* The following table help to decide if the operand are legal for the given */
/* operator. 5 entries for PLUS, MINUS, MULT, DIV, POWER. Each entry is a */
/* square matrix of number of object types by number of object types: */
static IritExprType OverLoadDiadicTable[5][9][9] =
/* POLY_EXPR NUMERIC_EXPR VECTOR_EXPR MATRIX_EXPR CURVE_EXPR SURFACE_EXPR STRING_EXPR OLST_EXPR CTLPT_EXPR */
{ { /* PLUS */
{ POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NUMERIC_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, VECTOR_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, MATRIX_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, CURVE_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, CURVE_EXPR },
{ POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, OLST_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, CURVE_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, CURVE_EXPR } },
{ /* MINUS */
{ POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NUMERIC_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, VECTOR_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, MATRIX_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR } },
{ /* MULT */
{ POLY_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NUMERIC_EXPR, VECTOR_EXPR, MATRIX_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, VECTOR_EXPR, NUMERIC_EXPR, VECTOR_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ POLY_EXPR, MATRIX_EXPR, VECTOR_EXPR, MATRIX_EXPR, CURVE_EXPR, SURFACE_EXPR, NO_EXPR, OLST_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, CURVE_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ POLY_EXPR, NO_EXPR, NO_EXPR, SURFACE_EXPR,NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, OLST_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR } },
{ /* DIV */
{ POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NUMERIC_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR } },
{ /* POWER */
{ POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NUMERIC_EXPR, NO_EXPR, MATRIX_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, MATRIX_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
{ NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR } },
};
/* The following table help to decide if the operand are legal for the given */
/* operator. 1 entry for UNARMINUS. Each entry is a linear vector of length */
/* of number of object types: */
static IritExprType OverLoadMonadicTable[1][9] =
/* POLY_EXPR NUMERIC_EXPR VECTOR_EXPR MATRIX_EXPR CURVE_EXPR SURFACE_EXPR STRING_EXPR OLST_EXPR CTLPT_EXPR */
{ /* UNARMINUS */
{ POLY_EXPR, NUMERIC_EXPR, VECTOR_EXPR, MATRIX_EXPR, CURVE_EXPR, SURFACE_EXPR, NO_EXPR, NO_EXPR, NO_EXPR }
};
static int OverLoadTypeCheckAux(int Operator, IritExprType Right,
IritExprType Left, IritExprType *Result);
static ObjectStruct *ConvSrfToPolys(ParseTree *Srf);
/*****************************************************************************
* Routine to perform type checking on the overloaded operators. Returns *
* TRUE if legal, and set Result to returned object type. *
* Allows multiple types (I.e. VECTOR_EXPR | MATRIX_EXPR is legal input). *
* Note output Result may be multiple types as well is a such case. *
*****************************************************************************/
int OverLoadTypeCheck(int Operator, IritExprType Right, IritExprType Left,
IritExprType *Result)
{
int i, j, NumRightTypes, NumLeftTypes;
IritExprType TmpResult;
/* Compute how many types are feasible here (input). */
for (i = 1, NumRightTypes = 0; i < ERROR_EXPR; i <<= 1)
NumRightTypes += (i & Right) != 0;
for (i = 1, NumLeftTypes = 0; i < ERROR_EXPR; i <<= 1)
NumLeftTypes += (i & Left) != 0;
if (NumLeftTypes < 1 || NumRightTypes < 1)
return FALSE;
else if (NumLeftTypes == 1 && NumRightTypes == 1)
return OverLoadTypeCheckAux(Operator, Right, Left, Result);
else {
/* More than one type in the input - compute union of the output */
/* types and return the union. */
*Result = 0;
for (i = 1; i < ERROR_EXPR; i <<= 1) if ((i & Right) != 0)
for (j = 1; j < ERROR_EXPR; j <<= 1) if ((j & Left) != 0) {
if (!OverLoadTypeCheckAux(Operator,
(IritExprType) i,
(IritExprType) j,
&TmpResult))
return FALSE;
*Result |= TmpResult;
}
return TRUE;
}
}
/*****************************************************************************
* Routine to perform type checking on the overloaded operators. Returns *
* TRUE if legal, and set Result to returned object type. *
* Assumes a single type (I.e. VECTOR_EXPR | MATRIX_EXPR is illegal input). *
*****************************************************************************/
static int OverLoadTypeCheckAux(int Operator, IritExprType Right,
IritExprType Left, IritExprType *Result)
{
int i, IRight, ILeft;
for (i = 1, IRight = 0; i < Right; i <<= 1, IRight++);
for (i = 1, ILeft = 0; i < Left; i <<= 1, ILeft++);
switch (Operator) {
case PLUS:
case MINUS:
case MULT:
case DIV:
case POWER:
*Result = OverLoadDiadicTable[Operator - OPERATORS_OFFSET]
[IRight][ILeft];
return *Result != NO_EXPR;
case UNARMINUS:
*Result = OverLoadMonadicTable[0][IRight];
return *Result != NO_EXPR;
default:
FatalError("OverLoadTypeCheck: undefined operator\n");
}
return FALSE; /* Makes warning silent. */
}
/*****************************************************************************
* Routine to evaluate an monadic or diadic expression. It is assumed the *
* two operands are valid for the given expression - a test which can be made *
* using OverLoadTypeCheck routine (see above). returned pointer to node with *
* the result, NULL in case of error (should not happen actually). *
* Root holds the simple sub-expression (Root has the operator). PObj holds *
* all the currently defined objects available in the system. IError & CError *
* will be set to relevant error if was one. *
*****************************************************************************/
ParseTree *OverLoadEvalOper(ParseTree *Root, ParseTree *TempR,
ParseTree *TempL, InptPrsrEvalErrType *IError, char *CError)
{
int i,
OperReversed = FALSE;
RealType R;
ParseTree *Temp,
*RetVal = Root;
ObjectStruct *TempLObj, *TempRObj;
switch (Root->NodeKind) { /* Dies if undefined operator. */
case PLUS:
case MINUS:
case MULT:
case DIV:
case POWER:
if (TempR == NULL || TempL == NULL) return NULL; /* Error! */
break;
case UNARMINUS:
if (TempR == NULL) return NULL; /* Error! */
break;
default:
FatalError("OverLoadEvalOper: Undefined operator\n");
}
/* Make TempL be bigger, so we need handle less cases. */
if (Root -> NodeKind != UNARMINUS &&
((int) TempR -> ObjType) > ((int) TempL -> ObjType)) {
Temp = TempR;
TempR = TempL;
TempL = Temp;
OperReversed = TRUE;
}
switch (Root->NodeKind) {
case PLUS:
if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
Root->ObjType = NUMERIC_OBJ;
Root->U.R = TempL->U.R + TempR->U.R;
}
else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
Root->ObjType = VECTOR_OBJ;
Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
PT_ADD(Root->U.PObj->U.Vec,
TempL->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
}
else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
Root->ObjType = MATRIX_OBJ;
Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
MatAddTwo4by4(Root->U.PObj->U.Mat,
TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
}
else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
(IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
TempLObj = ConvSrfToPolys(TempL);
TempRObj = ConvSrfToPolys(TempR);
Root->ObjType = POLY_OBJ;
Root->U.PObj = BooleanOR(TempLObj, TempRObj);
if (Root->U.PObj == NULL) {
IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
UpdateCharError("Operator ", PLUS);
RetVal = NULL;
}
}
else if (IS_OLST_NODE(TempR) && IS_OLST_NODE(TempL)) {
Root->ObjType = OBJ_LIST_OBJ;
Root->U.PObj = AppendLists(TempL->U.PObj, TempR->U.PObj);
}
else if ((IS_CTLPT_NODE(TempR) || IS_CRV_NODE(TempR)) &&
(IS_CTLPT_NODE(TempL) || IS_CRV_NODE(TempL))) {
Root->ObjType = CURVE_OBJ;
if (OperReversed)
Root->U.PObj = MergeCurvesAndCtlPoints(TempR->U.PObj,
TempL->U.PObj);
else
Root->U.PObj = MergeCurvesAndCtlPoints(TempL->U.PObj,
TempR->U.PObj);
}
else
RetVal = NULL;
break;
case MINUS:
if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
Root->ObjType = NUMERIC_OBJ;
Root->U.R = TempL->U.R - TempR->U.R;
}
else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
Root->ObjType = VECTOR_OBJ;
Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
PT_SUB(Root->U.PObj->U.Vec,
TempL->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
}
else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
Root->ObjType = MATRIX_OBJ;
Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
MatSubTwo4by4(Root->U.PObj->U.Mat,
TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
}
else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
(IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
TempLObj = ConvSrfToPolys(TempL);
TempRObj = ConvSrfToPolys(TempR);
Root->ObjType = POLY_OBJ;
Root->U.PObj = BooleanSUB(TempLObj, TempRObj);
if (Root->U.PObj == NULL) {
IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
UpdateCharError("Operator ", MINUS);
RetVal = NULL;
}
}
else
RetVal = NULL;
break;
case MULT:
if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
Root->ObjType = NUMERIC_OBJ;
Root->U.R = TempL->U.R * TempR->U.R;
}
else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
Root->ObjType = NUMERIC_OBJ;
Root->U.R = DOT_PROD(TempL->U.PObj->U.Vec,
TempR->U.PObj->U.Vec);
}
else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
Root->ObjType = MATRIX_OBJ;
Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
MatMultTwo4by4(Root->U.PObj->U.Mat,
TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
}
else if (IS_NUM_NODE(TempR) && IS_VEC_NODE(TempL)) {
Root->ObjType = VECTOR_OBJ;
Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
PT_COPY(Root->U.PObj->U.Vec, TempL->U.PObj->U.Vec);
PT_SCALE(Root->U.PObj->U.Vec, TempR->U.R);
}
else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
Root->ObjType = MATRIX_OBJ;
Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
MatScale4by4(Root->U.PObj->U.Mat,
TempL->U.PObj->U.Mat, &TempR->U.R);
}
else if (IS_POLY_NODE(TempR) && IS_MAT_NODE(TempL)) {
Root->U.PObj = TransformObject(TempR->U.PObj,
TempL->U.PObj->U.Mat);
Root->ObjType = POLY_OBJ;
}
else if ((IS_MAT_NODE(TempR) && IS_CRV_NODE(TempL)) ||
(IS_MAT_NODE(TempR) && IS_SRF_NODE(TempL)) ||
(IS_MAT_NODE(TempR) && IS_OLST_NODE(TempL))) {
Root->U.PObj = TransformObject(TempL->U.PObj,
TempR->U.PObj->U.Mat);
Root->ObjType = Root->U.PObj->ObjType;
}
else if (IS_VEC_NODE(TempR) && IS_MAT_NODE(TempL)) {
Root->ObjType = VECTOR_OBJ;
Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
MatMultVecby4by4(Root->U.PObj->U.Vec,
TempR->U.PObj->U.Vec, TempL->U.PObj->U.Mat);
}
else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
(IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
TempLObj = ConvSrfToPolys(TempL);
TempRObj = ConvSrfToPolys(TempR);
Root->ObjType = POLY_OBJ;
Root->U.PObj = BooleanAND(TempLObj, TempRObj);
if (Root->U.PObj == NULL) {
IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
UpdateCharError("Operator ", MULT);
RetVal = NULL;
}
}
else
RetVal = NULL;
break;
case DIV:
if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) { /* Numeric div. */
Root->ObjType = NUMERIC_OBJ;
if (Root->Right->U.R != 0.0) {
Root->U.R = TempL->U.R / TempR->U.R;
}
else {
*IError = IE_ERR_DIV_BY_ZERO;
strcpy(CError, "/");
RetVal = NULL;
}
}
else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
(IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
TempLObj = ConvSrfToPolys(TempL);
TempRObj = ConvSrfToPolys(TempR);
Root->ObjType = POLY_OBJ;
Root->U.PObj = BooleanCUT(TempLObj, TempRObj);
if (Root->U.PObj == NULL) {
IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
UpdateCharError("Operator ", DIV);
RetVal = NULL;
}
}
else
RetVal = NULL;
break;
case POWER:
if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {/* Numeric power. */
Root->ObjType = NUMERIC_OBJ;
Root->U.R = pow(TempL->U.R, TempR->U.R);
}
else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
i = (int) TempR->U.R; /* Power MUST be integer in this case. */
if (!APX_EQ(i, TempR->U.R) || i < -1) {
*IError = IE_ERR_MAT_POWER;
strcpy(CError, "^");
RetVal = NULL;
}
Root->ObjType = MATRIX_OBJ;
Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
if (i == -1) { /* Generate the inverse matrix: */
if (!MatInverseMatrix(TempL->U.PObj->U.Mat,
Root->U.PObj->U.Mat)) {
*IError = IE_ERR_MAT_POWER;
strcpy(CError, "^");
RetVal = NULL;
}
}
else { /* I must be positive integer. */
MatGenUnitMat(Root->U.PObj->U.Mat);
while (i--) MatMultTwo4by4(Root->U.PObj->U.Mat,
Root->U.PObj->U.Mat,
TempL->U.PObj->U.Mat);
}
}
else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
(IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
TempLObj = ConvSrfToPolys(TempL);
TempRObj = ConvSrfToPolys(TempR);
Root->ObjType = POLY_OBJ;
Root->U.PObj = BooleanMERGE(TempLObj, TempRObj);
if (Root->U.PObj == NULL) {
IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
UpdateCharError("Operator ", MINUS);
RetVal = NULL;
}
}
else
RetVal = NULL;
break;
case UNARMINUS:
if (IS_NUM_NODE(TempR)) {
Root->ObjType = NUMERIC_OBJ;
Root->U.R = -TempR->U.R;
}
else if (IS_VEC_NODE(TempR)) {
Root->ObjType = VECTOR_OBJ;
Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
PT_COPY(Root->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
PT_SCALE(Root->U.PObj->U.Vec, -1.0);
}
else if (IS_MAT_NODE(TempR)) {
Root->ObjType = MATRIX_OBJ;
Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
R = -1.0;
MatScale4by4(Root->U.PObj->U.Mat, TempR->U.PObj->U.Mat, &R);
}
else if (IS_POLY_NODE(TempR)) {
Root->ObjType = POLY_OBJ;
Root->U.PObj = BooleanNEG(TempR -> U.PObj);
}
else if (IS_CRV_NODE(TempR)) {
Root->ObjType = CURVE_OBJ;
Root->U.PObj = CurveReverse(TempR -> U.PObj);
}
else if (IS_SRF_NODE(TempR)) {
Root->ObjType = SURFACE_OBJ;
Root->U.PObj = SurfaceReverse(TempR -> U.PObj);
}
else
RetVal = NULL;
break;
}
if (RetVal == NULL && *IError == IPE_NO_ERR) { /* Put general error msg: */
*IError = IE_ERR_TYPE_MISMATCH;
switch (Root->NodeKind) {
case PLUS:
strcpy(CError, "Operator +");
break;
case MINUS:
strcpy(CError, "Operator -");
break;
case MULT:
strcpy(CError, "Operator *");
break;
case DIV:
strcpy(CError, "Operator /");
break;
case POWER:
strcpy(CError, "Operator ^");
break;
case UNARMINUS:
strcpy(CError, "Operator (unary) -");
break;
}
}
return RetVal;
}
/*****************************************************************************
* If given object is a surface, its polygonal representation object is *
* returned instead. Otherwise the given pointer is returned as is. *
*****************************************************************************/
static ObjectStruct *ConvSrfToPolys(ParseTree *Srf)
{
if (!IS_SRF_NODE(Srf)) return Srf -> U.PObj;
if (Srf -> U.PObj -> U.Srf.Polygons == NULL)
ComputeSurfacePolygons(Srf -> U.PObj);
return Srf -> U.PObj -> U.Srf.Polygons;
}